/**
 * @(#)SimulatorManager.java 2016年11月4日
 * Copyright(C) 2016 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service;

import org.apache.commons.lang.StringUtils;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.domian.SimulatorInfoVo;
import org.jsbd.boss.domian.channel.ApkSimulator;
import org.jsbd.boss.service.impl.CacheParamManager;
import org.jsbd.boss.util.CacheKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 模拟器管理
 *
 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
 * @version 1.0.0
 */
@Service
public class SimulatorManager {
    public static final Logger LOGGER = LoggerFactory.getLogger(SimulatorManager.class);

    @Resource
    private IApkSimulatorService apkSimulatorService;
    @Resource
    private RedisClient<String, Object> redisClient;

    @Resource
    private RedisClient<String, Object> redisClientTemp;

    @Resource
    private CacheParamManager cacheParamManager;

    private Integer GROUP_NUM = 100;


    /**
     * addSimulator:将访问的设备信息保存
     *
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public void addSimulator(SimulatorInfoVo simulator) {
        simulator.setCurrentTime(System.currentTimeMillis());
        String uuid = simulator.getUuid();
        String hashKey = getSimulatorHashKey(uuid);
        redisClientTemp.putHash(hashKey, uuid, simulator);
    }


    public String getSimulatorHashKey(String uuid) {
        int groupIndex = Math.abs(uuid.hashCode()) % GROUP_NUM;
        return CacheKey.ONLINE_SIMULATORS_HASH_KEY + groupIndex;
    }

    public String getSimulatorHashKey(int groupIndex) {
        return CacheKey.ONLINE_SIMULATORS_HASH_KEY + groupIndex;
    }

    public void removeSimulator(String uuid){
        int groupIndex = Math.abs(uuid.hashCode()) % GROUP_NUM;
        String cacheKey = CacheKey.ONLINE_SIMULATORS_HASH_KEY + groupIndex;
        redisClientTemp.removeHash(cacheKey, uuid);
    }


    /**
     * getApkSimulators:apk的可用模拟器是否大于0
     *
     * @param simulators
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public Map<String, Boolean> getApkSimulators(List<ApkSimulator> simulators) {
        Map<String, Boolean> map = new HashMap<String, Boolean>();
        if (simulators != null && simulators.size() > 0) {
            Map<String, Integer> verMap = getSimulatorOfVer();
            for (ApkSimulator apk : simulators) {
                String mark = apk.getMark();
                String sysVer = apk.getSysVer();
                Integer verNum = verMap.get(sysVer);
                if (verNum != null && verNum > 0) {
                    map.put(mark, true);
                }
            }
        }
        return map;
    }

    /**
     * getSimulatorCountOfVer:版本号对应的模拟器 可用模拟器数量
     * modify by zhouc 2018-04-12
     *
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public Map<String, Integer> getSimulatorOfVer() {
        // 查询没有任务的模拟器
        return this.getOnlineSimulators(false);
    }

    /**
     * getDevices:获取所有在线的设备
     *
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public Map<String, Integer> getOnlineSimulators(Boolean isBusy) {
        //modify by zhouc 2018-04-12
        Map<String, Integer> resultMap = getOnlineSimulatorsNum(isBusy);

        long now = System.currentTimeMillis();
        Object expreTime = cacheParamManager.getParamValue(CacheKey.ONLINE_SIMULATORS_TIME);
        long startTime = 0;
        if (expreTime != null) {
            startTime = now - Integer.parseInt(expreTime.toString()) * 1000;
        }
        Map<Object, Object> simulatorMap = getAllSimulatorMap();
        if (simulatorMap == null || simulatorMap.isEmpty()) {
            return resultMap;
        }

        for (Entry<Object, Object> entity : simulatorMap.entrySet()) {
            SimulatorInfoVo simulatorInfoVo = (SimulatorInfoVo) entity.getValue();
            // 超时的就不要了
            if (simulatorInfoVo.getCurrentTime() < startTime) {
                removeSimulator(simulatorInfoVo.getUuid());
                continue;
            }
            if (simulatorInfoVo.isBusy() == isBusy.booleanValue()) {
                String sysVer = simulatorInfoVo.getSysVer();
                Integer num = resultMap.get(sysVer);
                if (num == null) {
                    num = 0;
                }
                resultMap.put(sysVer, num + 1);
            }
        }

        return resultMap;
    }

    /**
     * 获取长连接的在线模拟器数量
     *
     * @param isBusy
     * @return
     * @author <a href="mailto:zhouchao@zhexinit.com" >周超</a>
     */
    public Map<String, Integer> getOnlineSimulatorsNum(Boolean isBusy) {
        Map<String, Integer> resultMap = new HashMap<String, Integer>();

        //这里只存储版本对应的空闲数量有多少，总的模拟器有多少，格式如下：
        //key=${version}_unbusy/total,value=数量
        Map<Object, Object> simulatorMap = redisClient.getHash(CacheKey.CLMAP_VERSION_NUM_KEY);
        if (simulatorMap == null || simulatorMap.isEmpty()) {
            return resultMap;
        }

        for (Entry<Object, Object> entity : simulatorMap.entrySet()) {
            String versionKey = (String) entity.getKey();

            if (StringUtils.isBlank(versionKey)) {
                continue;
            }
            int idx = versionKey.lastIndexOf("_");
            if (idx < 1) {
                continue;
            }
            String version = versionKey.substring(0, idx);
            String workFlag = versionKey.substring(idx + 1);

            Integer simulatorNum = (Integer) entity.getValue();
            if (simulatorNum == null) {
                simulatorNum = 0;
            }

            Integer num = resultMap.get(version);
            if (num == null) {
                num = 0;
            }

            if (isBusy) {
                if ("unbusy".equals(workFlag)) {
                    simulatorNum = 0 - simulatorNum;
                }
            } else {
                if (!"unbusy".equals(workFlag)) {
                    continue;
                }
            }
            resultMap.put(version, num + simulatorNum);
        }
        return resultMap;
    }

    public Map<Object, Object> getAllSimulatorMap() {
        Map<Object, Object> simulatorMap = new HashMap<>();
        for (int i = 0; i < GROUP_NUM; i++) {
            Map<Object, Object> groupMap = redisClientTemp.getHash(getSimulatorHashKey(i));
            if (groupMap != null && !groupMap.isEmpty()) {
                simulatorMap.putAll(groupMap);
            }
        }
        return simulatorMap;
    }


    /**
     * 获取各版本在线模拟器数量以及总的模拟器数据量
     *
     * @return
     * @author <a href="mailto:zhouchao@zhexinit.com" >周超</a>
     */
    public Map<String, Integer> getOnlineSimulatorNum() {
        Map<String, Integer> numMap = new HashMap<String, Integer>();

        long now = System.currentTimeMillis();
        Object expreTime = cacheParamManager.getParamValue(CacheKey.ONLINE_SIMULATORS_TIME);
        long startTime = 0;
        if (expreTime != null) {
            startTime = now - Integer.parseInt(expreTime.toString()) * 1000;
        }

        Map<Object, Object> simulatorMap = getAllSimulatorMap();
        if (simulatorMap == null || simulatorMap.isEmpty()) {
            return numMap;
        }

        int totalNum = 0;
        for (Entry<Object, Object> entity : simulatorMap.entrySet()) {
            SimulatorInfoVo simulatorInfoVo = (SimulatorInfoVo) entity.getValue();
            // 超时的就不要了
            if (simulatorInfoVo.getCurrentTime() < startTime) {
                removeSimulator(simulatorInfoVo.getUuid());
                continue;
            }

            Integer num = numMap.get(simulatorInfoVo.getSysVer());
            if (num == null) {
                num = 0;
            }
            num++;
            totalNum++;
            numMap.put(simulatorInfoVo.getSysVer(), num);
        }

        Map<String, Integer> clVerNumMap = getOnlineSimulatorsTotalNum();

        for (Entry<String, Integer> entity : clVerNumMap.entrySet()) {
            String version = entity.getKey();
            Integer num = numMap.get(version);
            if (num == null) {
                num = 0;
            }
            numMap.put(version, num + entity.getValue());
            totalNum += entity.getValue();
        }

        numMap.put("totalNum", totalNum);

        return numMap;
    }

    /**
     * 获取长连接的在线模拟器总的数量
     *
     * @return
     * @author <a href="mailto:zhouchao@zhexinit.com" >周超</a>
     */
    public Map<String, Integer> getOnlineSimulatorsTotalNum() {
        Map<String, Integer> resultMap = new HashMap<String, Integer>();

        //这里只存储版本对应的空闲数量有多少，总的模拟器有多少，格式如下：
        //key=${version}_unbusy/total,value=数量
        Map<Object, Object> simulatorMap = redisClient.getHash(CacheKey.CLMAP_VERSION_NUM_KEY);
        if (simulatorMap == null || simulatorMap.isEmpty()) {
            return resultMap;
        }

        for (Entry<Object, Object> entity : simulatorMap.entrySet()) {
            String versionKey = (String) entity.getKey();

            if (StringUtils.isBlank(versionKey)) {
                continue;
            }
            int idx = versionKey.lastIndexOf("_");
            if (idx < 1) {
                continue;
            }
            String version = versionKey.substring(0, idx);
            String workFlag = versionKey.substring(idx + 1);

            Integer simulatorNum = (Integer) entity.getValue();
            if (simulatorNum == null) {
                simulatorNum = 0;
            }

            Integer num = resultMap.get(version);
            if (num == null) {
                num = 0;
            }

            if (!"total".equals(workFlag)) {
                continue;
            }
            resultMap.put(version, num + simulatorNum);
        }
        return resultMap;
    }


    /**
     * addVerCanUseSimulator:版本号下每个apk可用模拟器
     *
     * @param apkSimulator
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public void addVerCanUseSimulator(ApkSimulator apkSimulator) {
        redisClient.put(CacheKey.APK_SIMULATOR_NUM_KEY + apkSimulator.getSysVer(), apkSimulator.getCount().intValue(), 120);
    }

    /**
     * getVerCanUseSimulator:版本下可用模拟器数量
     *
     * @param sysVer
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public Integer getVerCanUseSimulator(String sysVer) {
        Object numObj = redisClient.get(CacheKey.APK_SIMULATOR_NUM_KEY + sysVer);
        if (numObj != null) {
            return Integer.parseInt(numObj.toString());
        } else {
            return 0;
        }

    }

    /**
     * getApkCanUseSimulator:获取apk可用模拟器数量
     *
     * @param apk
     * @return
     * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
     */
    public Integer getApkCanUseSimulator(String apk) {
        String ver = apkSimulatorService.getVer(apk);
        return getVerCanUseSimulator(ver);
    }


}

